package com.syh.core.ddd.service;

import cn.redscarf.commons.util.bean.ExtBeanUtils;
import cn.redscarf.commons.wrapper.Wrapper;
import com.syh.core.ddd.domain.Aggregate;
import com.syh.core.ddd.domain.DomainEvent;
import com.syh.core.ddd.event.DomainEventBus;
import com.syh.core.ddd.infrastructure.repository.AggregateRepository;
import com.syh.core.expction.UnexpectedlyException;
import com.syh.jn.scm.infrastructure.eventBus.reflex.ReflexEventBus;
import com.syh.jn.scm.service.core.BaseService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.stream.Collectors;

@Transactional
public abstract class AbstractServiceImpl<Sto, Mto, Vo, Entity extends Aggregate<Key>, Key extends Serializable> implements BaseService<Sto, Mto, Vo, Key> {

  // 实体类类型(由构造方法自动赋值)
  private Class<Entity> entityClass = null;
  private Class<Vo> voClass = null;

  protected Logger logger = LoggerFactory.getLogger(this.getClass());

  abstract protected AggregateRepository<Entity, Key> getAggregateRepository();

  /**
   * 构造方法，根据实例类自动获取实体类类型
   */
  public AbstractServiceImpl() {
    Class c = this.getClass();
    Type t = c.getGenericSuperclass();
    if (t instanceof ParameterizedType) {
      Type[] p = ((ParameterizedType) t).getActualTypeArguments();
      this.entityClass = (Class<Entity>) p[0];
      this.voClass = (Class<Vo>) p[2];
    }
  }

  /**
   * 根据id获取
   *
   * @param key
   * @return
   */
  @Override
  public Vo getById(Key key) {
    return this.getAggregateRepository().getKeyView((Key) key);
  }

  @Override
  public boolean contains(Key key) {
    return this.getAggregateRepository().contains(key);
  }

  /**
   * 根据查询条件获取第一条数据
   *
   * @param wrapper
   * @return
   */
  @Override
  public Vo getOne(Wrapper wrapper) {

    List<Vo> entityList = this.findListPage(wrapper, 1, 1);

    return entityList.isEmpty() ? null : entityList.get(0);
  }

  /**
   * 根据条件获取查询列表
   *
   * @param wrapper
   * @return
   */
  @Override
  public List<Vo> findList(Wrapper wrapper) {
    List<Vo> entityList = this.getAggregateRepository().getListView(wrapper);
    return entityList;
  }

  /**
   * 根据条件获取查询列表分页
   *
   * @param wrapper
   * @param startRow
   * @param count
   * @return
   */
  @Override
  public List<Vo> findListPage(Wrapper wrapper, Integer startRow, Integer count) {
    List<Vo> voList = this.getAggregateRepository().findListPageView(wrapper, startRow, count);
    return voList;
  }

  /**
   * 内部方法  业务模型转Vo
   *
   * @param entityList
   * @return
   */
  private List<Vo> transform(List<Entity> entityList) {
    List<Vo> voList = entityList.stream().map((entity) -> {
      Vo vo = null;
      try {
        vo = voClass.newInstance();
        ExtBeanUtils.copyProperties(entity, vo);
      } catch (Exception e) {
        throw new UnexpectedlyException("初始化 Vo 异常");
      }
      return vo;
    }).collect(Collectors.toList());
    return voList;
  }

  @Override
  public int getCount(Wrapper wrapper) {
    return this.getAggregateRepository().getCount(wrapper);
  }

  @Override
  public int getCountView(Wrapper wrapper) {
    return this.getAggregateRepository().getCountView(wrapper);
  }


  /**
   * 发布事件,解耦服务之间的耦合
   *
   * @param event
   */
  public void publicEvent(DomainEvent event) {
    DomainEventBus bus = ReflexEventBus.getEventBus();
    bus.publicEvent(event);
  }
}
